package com.macxen.record;


import android.app.Application;
import android.util.Log;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Arrays;

/**
 * Created by chenjim on 2016/9/26.
 * 可以打印当前的线程名，所在代码中的位置等信息
 * modify from {@link "https://github.com/orhanobut/logger"}
 */
public class Loger {
    /**
     * Android's max limit for a log entry is ~4076 bytes,
     * so 4000 bytes is used as chunk size since default charset
     * is UTF-8
     */
    private static final int CHUNK_SIZE = 4000;

    /**
     * TAG is used for the Log, the name is a little different
     * in order to differentiate the logs easily with the filter
     */
    private static String TAG = null;

    /**
     * true 输出日志
     * false 不输出日志
     */
    private static boolean isDebug = true;

    /**
     * 不对Loger进一步封装，为4
     * 若进一步封装，此值需要改变
     */
    private static int stackIndex = 4;

    /**
     * 日志内容写入到文件，默认不写
     * 可以通过广播打开此值
     */
    private static boolean logToFile = false;

    private static File logFile;

    private static SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

    private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

    private static Application application;

    /**
     * @param app    Application
     * @param debug  true or false.when release,you'd better set false. {@link #isDebug}
     * @param toFile true 记录，false 不记录，默认值
     */
    public static void init(Application app, boolean debug, boolean toFile) {
        application = app;
        isDebug = debug;
        logToFile = toFile;
    }

    public static void d() {
        log(Log.DEBUG, TAG, " ");
    }

    public static void d(Object object) {
        String message;
        if (object == null) {
            message = "null";
        } else if (object.getClass().isArray()) {
            message = Arrays.deepToString((Object[]) object);
        } else {
            message = object.toString();
        }
        log(Log.DEBUG, TAG, message);
    }

    public static void d(String tag, String message) {
        log(Log.DEBUG, tag, message);
    }


    public static void e(Object object) {
        String message;
        if (object == null) {
            message = "null";
        } else if (object.getClass().isArray()) {
            message = Arrays.deepToString((Object[]) object);
        } else {
            message = object.toString();
        }
        log(Log.ERROR, TAG, message);
    }

    public static void e(String tag, String message) {
        log(Log.ERROR, tag, message);
    }

    public static void e(String tag, Exception e) {
        String message = null;
        if (e != null) {
            message = e.toString();
        }
        if (message == null) {
            message = "No message/exception is set";
        }
        log(Log.ERROR, tag, message);
    }

    public static void e(String tag, String message, Exception e) {

        if (e != null && message != null) {
            message += " : " + e.toString();
        }
        if (e != null && message == null) {
            message = e.toString();
        }
        if (message == null) {
            message = "No message/exception is set";
        }
        log(Log.ERROR, tag, message);
    }


    public static void w(Object object) {
        String message;
        if (object == null) {
            message = "null";
        } else if (object.getClass().isArray()) {
            message = Arrays.deepToString((Object[]) object);
        } else {
            message = object.toString();
        }
        log(Log.WARN, TAG, message);
    }

    public static void w(String tag, String message) {
        log(Log.WARN, tag, message);
    }

    public static void i() {
        log(Log.INFO, TAG, " ");
    }

    public static void i(Object object) {
        String message;
        if (object == null) {
            message = "null";
        } else if (object.getClass().isArray()) {
            message = Arrays.deepToString((Object[]) object);
        } else {
            message = object.toString();
        }
        log(Log.INFO, TAG, message);
    }

    public static void i(String tag, String message) {
        log(Log.INFO, tag, message);
    }


    public static void v() {
        log(Log.VERBOSE, TAG, " ");
    }

    public static void v(String message) {
        log(Log.VERBOSE, TAG, message);
    }


    public static void v(String tag, String message) {
        log(Log.VERBOSE, tag, message);
    }

    public static void wtf() {
        log(Log.ASSERT, TAG, " ");
    }

    public static void wtf(String message) {
        log(Log.ASSERT, TAG, message);
    }

    public static void wtf(String tag, String message) {
        log(Log.ASSERT, tag, message);
    }

    private static void log(int logType, String tag, String message) {
        if (!isDebug) {
            return;
        }

        if (application == null) {
            throw new NullPointerException("application is null");
        }

        if (tag == null) {
            tag = application.getPackageName();
        }

        StackTraceElement[] trace = Thread.currentThread().getStackTrace();

        String simpleClassName = //trace[stackIndex].getFileName();
                getSimpleClassName(trace[stackIndex].getClassName());

        StringBuilder builder = new StringBuilder();
        builder.append(Thread.currentThread().getName())
                .append(",")
                .append("(")
                .append(trace[stackIndex].getFileName())
                .append(":")
                .append(trace[stackIndex].getLineNumber())
                .append("),")
                .append(trace[stackIndex].getMethodName())
                .append("():")
        ;

        if (message == null) {
            message = "null";
        }

        //get bytes of message with system's default charset (which is UTF-8 for Android)
        byte[] bytes = message.getBytes();
        int length = bytes.length;

        for (int i = 0; i < length; i += CHUNK_SIZE) {
            int count = Math.min(length - i, CHUNK_SIZE);
            //create a new String with system's default charset (which is UTF-8 for Android)
            String content = new String(bytes, i, count);
            String finalContent = builder.toString() + content;
            logChunk(logType, tag, finalContent);
            writeLogToFile(finalContent);
        }
    }


    private synchronized static void writeLogToFile(String msg) {
        if (!logToFile) {
            return;
        }
//
//        String time = timeFormat.format(new Date());
//        String date = dateFormat.format(new Date());
//
//        msg = time + " " + msg + "\r";
//        logFile = new File(StorageUtil.getLogStoragePath(), "log_" + date + ".txt");
//
//        FileUtil.write(logFile, msg, true, true);
    }

    private static String getSimpleClassName(String name) {
        int lastIndex = name.lastIndexOf(".");
        return name.substring(lastIndex + 1);
    }

    private static void logChunk(int logType, String tag, String chunk) {
        switch (logType) {
            case Log.ERROR:
                Log.e(tag, chunk);
                break;
            case Log.INFO:
                Log.i(tag, chunk);
                break;
            case Log.VERBOSE:
                Log.v(tag, chunk);
                break;
            case Log.WARN:
                Log.w(tag, chunk);
                break;
            case Log.ASSERT:
                Log.wtf(tag, chunk);
                break;
            case Log.DEBUG:
                // Fall through, log debug by default
            default:
                Log.d(tag, chunk);
                break;
        }
    }

}
